package com.glance.browser.domain;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.Size;

import org.springframework.format.annotation.DateTimeFormat;

@Entity
@Table(name="KnowledgeClass")
public class KnowledgeClass implements Serializable{

	public KnowledgeClass(User owner, Set<KnowledgeItem> knowledgeItems,
			Set<KnowledgeClass> parentClasses, String title,
			String description, Date publisherDate) {
		super();
		this.owner = owner;
		this.knowledgeItems = knowledgeItems;
		this.parentClasses = parentClasses;
		this.title = title;
		this.description = description;
		this.publisherDate = publisherDate;
	}

	private static final long serialVersionUID = -4717297082747677747L;

	@ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.EAGER )
    	@JoinColumn(name="username")
    private User owner;
	
	@ManyToMany(fetch = FetchType.LAZY, mappedBy = "knowledgeClasses")
	private Set<KnowledgeItem> knowledgeItems = new HashSet<KnowledgeItem>();
	
	@ManyToMany(cascade = CascadeType.ALL)
	@JoinTable(name = "KnowledgeClassAssociation", 
		joinColumns = { @JoinColumn(name = "child_id", referencedColumnName = "class_id")}, 
		inverseJoinColumns = { @JoinColumn(name = "parent_id") })
	private Set<KnowledgeClass> parentClasses = new HashSet<KnowledgeClass>();
	
	@ManyToMany(fetch = FetchType.LAZY, mappedBy = "parentClasses")
	private Set<KnowledgeClass> knowledgeClasses = new HashSet<KnowledgeClass>();
		
	@OneToMany (mappedBy="knowledgeClass", cascade={CascadeType.PERSIST, CascadeType.REMOVE})
	private Set<History> changes = new HashSet<History>();
	
	// Persistent Fields:
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "class_id")
    private Long id;
    
    @Column(name = "version", nullable = false, columnDefinition = "int default 0")
    private int version = 0;
    
    @Column(name = "title", length = 45)
    @Size(min=1)
    private String title;
    
    @Column(name = "description", length = 200)
    private String description;
    
    @Column(name = "publisher_date")
	@Temporal(TemporalType.DATE)
	@DateTimeFormat(style = "M-")
    private Date publisherDate;
    
    // Constructors:
    public KnowledgeClass() {
	}

	// String Representation:
    @Override
    public String toString() {
        return title;
    }

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public User getOwner() {
		return owner;
	}

	public void setOwner(User owner) {
		this.owner = owner;
	}

	public Set<KnowledgeItem> getKnowledgeItems() {
		return knowledgeItems;
	}

	public void setKnowledgeItems(Set<KnowledgeItem> knowledgeItems) {
		this.knowledgeItems = knowledgeItems;
	}

	public Set<KnowledgeClass> getParentClasses() {
		return parentClasses;
	}

	public void setParentClasses(Set<KnowledgeClass> parentClasses) {
		this.parentClasses = parentClasses;
	}

	public Set<KnowledgeClass> getKnowledgeClasses() {
		return knowledgeClasses;
	}

	public void setKnowledgeClasses(Set<KnowledgeClass> knowledgeClasses) {
		this.knowledgeClasses = knowledgeClasses;
	}

	public Set<History> getChanges() {
		return changes;
	}

	public void setChanges(Set<History> changes) {
		this.changes = changes;
	}

	public Long getClassId() {
		return id;
	}

	public void setClassId(Long classId) {
		this.id = classId;
	}

	public int getVersion() {
		return version;
	}

	public void setVersion(int version) {
		this.version = version;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public Date getPublisherDate() {
		return publisherDate;
	}

	public void setPublisherDate(Date publisherDate) {
		this.publisherDate = publisherDate;
	}
}
